const axios = require('axios');
const amqp = require('../../module/message-queue/amqp');
const appId = '643b72a97aa6e198e1fd4a20';
const appClientId = '149255680903168';
const appClientSecret = '13a2fd47-4b63-4d25-96b9-2816801b1314';

// 信用金还款场景id
const creditPaymentSceneId = '643b74477aa6e198e1fd4a3b';
// 商品购买场景id
const goodsBugPaymentSceneId = '643e49b9d3f4726fbede6e28';
// 余额充值场景id
const balanceChargeSceneId = '643e498bd3f4726fbede6e22';
// 退款场景id
const refundSceneId = '643b74917aa6e198e1fd4a41';

const paymentOrderStatusExchangeName = 'payment-order-status-notify';

let baseURL = 'https://backend-production-payment-merchant.svc.tegical.world/api/v1/client';
if (process.env.NODE_ENV === 'trial') {
    baseURL = 'https://backend-production-payment-merchant.svc.tegical.world/api/v1/client';
}
if (process.env.NODE_ENV === 'development') {
    baseURL = 'https://backend-production-payment-merchant.svc.tegical.world/api/v1/client';
}

const axiosInstance = axios.create({
    baseURL,
    timeout: 30 * 1000,
    headers: {
        'Content-Type': 'application/json',
        authorization: 'Basic ' + Buffer.from(`${appClientId}:${appClientSecret}`).toString('base64')
    }
});

/**
 * @typedef {Object} RequestPaymentResult
 * @property {string} orderId 订单id
 * @property {Object} paySign 支付签名
 */

/**
 * @Description 请求支付订单
 * @author charzhou
 * @date 2023/4/10 23:30
 * @param sceneId 支付场景id
 * @param openId 用户openId
 * @param totalAmount 订单总金额
 * @param description 订单描述
 * @return {Promise<RequestPaymentResult>}
 */
async function requestPaymentOrder (sceneId, openId, totalAmount, description) {
    const res = await axiosInstance.post(`/scene/id/${sceneId}/invoke`, {
        params: {
            openId,
            totalAmount,
            description
        }
    });
    return res.data.data;
}

/**
 * @typedef {Object} PaymentOrder 支付订单
 * @property {string} id 订单id
 * @property {string} status 订单状态
 */

/**
 * @Description 查询支付订单
 * @author charzhou
 * @date 2023/4/10 23:37
 * @param paymentOrderId 支付订单id
 * @return {Promise<PaymentOrder>}
 */
async function queryPaymentOrder (paymentOrderId) {
    const res = await axiosInstance.get(`/payment-order/id/${paymentOrderId}`);
    return res.data.data;
}

/**
 * @typedef {Object} RefundOrder 退款订单
 * @property {string} id 订单id
 * @property {string} status 订单状态
 */

/**
 * @typedef {Object} RequestRefundResult
 * @property {string} orderId 订单id
 */

/**
 * @Description 请求订单退款
 * @author charzhou
 * @date 2023/4/12 18:57
 * @param refundSceneId 退款场景id
 * @param paymentOrderId 支付订单id
 * @param totalAmount 订单总金额
 * @param refundAmount 退款金额
 * @param reason 退款原因
 * @return {Promise<RequestRefundResult>}
 */
async function requestOrderRefund (refundSceneId, paymentOrderId, totalAmount, refundAmount, reason) {
    const res = await axiosInstance.post(`/scene/id/${refundSceneId}/invoke`, {
        params: {
            paymentOrderId,
            totalAmount,
            refundAmount,
            reason
        }
    });
    return res.data.data;
}

/**
 * @Description 查询退款订单
 * @author charzhou
 * @date 2023/4/12 18:58
 * @param refundOrderId 退款订单id
 * @return {Promise<RefundOrder>}
 */
async function queryRefundOrder (refundOrderId) {
    const res = await axiosInstance.get(`/refund-order/id/${refundOrderId}`);
    return res.data.data;
}

/**
 * @Description 支付订单状态监听回调
 * @author charzhou
 * @date 2023/4/17 23:02
 * @callback PaymentOrderStatusListenerCallback
 * @param {string} paymentOrderId 支付订单id
 * @param {string} status 支付订单状态
 * @return {Promise<void>}
 */

/**
 * @Description 添加支付订单状态监听器
 * @author charzhou
 * @date 2023/4/17 22:59
 * @param sceneId 场景id
 * @param {PaymentOrderStatusListenerCallback} callback 回调函数
 * @return {Promise<void>}
 */
async function addPaymentOrderStatusListener (sceneId, callback) {
    const connection = await amqp.getAmqpConnection();
    const channel = await connection.createChannel();
    await channel.assertExchange(paymentOrderStatusExchangeName, 'topic');
    const { queue } = await channel.assertQueue(null, { durable: false, exclusive: true });
    await channel.consume(queue, async (msg) => {
        const data = JSON.parse(msg.content.toString());
        const { id: paymentOrderId, status } = data;
        try {
            await callback(paymentOrderId, status);
            channel.ack(msg);
        } catch (e) {
            channel.nack(msg);
        }
    });
    await channel.bindQueue(queue, paymentOrderStatusExchangeName, `${appId}.${sceneId}`);
}

module.exports = {
    requestPaymentOrder,
    queryPaymentOrder,

    requestOrderRefund,
    queryRefundOrder,

    addPaymentOrderStatusListener,

    creditPaymentSceneId,
    balanceChargeSceneId,
    goodsBugPaymentSceneId,
    refundSceneId
};
